import mistune

from django.contrib.auth.models import User
from django.db import models
from django.utils.functional import cached_property


class Category(models.Model):
    STATUS_NORMAL = 1
    STATUS_DELETE = 0
    STATUS_ITEMS = (
        (STATUS_NORMAL, 'Normal'),
        (STATUS_DELETE, 'Delete')
    )
    name = models.CharField(max_length=50, verbose_name='Category Name')
    status = models.IntegerField(default=STATUS_NORMAL, choices=STATUS_ITEMS, verbose_name='Category Status')
    owner = models.ForeignKey(User, verbose_name='Author', on_delete=models.DO_NOTHING)
    created_time = models.DateTimeField(auto_now_add=True, editable=False, verbose_name='Create Time')
    is_nav = models.BooleanField(default=False, verbose_name='Is Nav')

    class Meta:
        verbose_name = verbose_name_plural = 'Category Table'

    def __str__(self):
        return self.name

    @classmethod
    def get_navs(cls):
        categories = cls.objects.filter(status=cls.STATUS_NORMAL)
        nav_categories = []
        normal_categories = []
        for c in categories:
            if c.is_nav:
                nav_categories.append(c)
            else:
                normal_categories.append(c)
        return {
            'navs': nav_categories,
            'categories': normal_categories
        }


class Tag(models.Model):
    STATUS_NORMAL = 1
    STATUS_DELETE = 0
    STATUS_ITEMS = (
        (STATUS_NORMAL, 'Normal'),
        (STATUS_DELETE, 'Delete')
    )
    name = models.CharField(max_length=10, verbose_name='Tag Name')
    status = models.IntegerField(default=STATUS_NORMAL, choices=STATUS_ITEMS, verbose_name='Tag Status')
    owner = models.ForeignKey(User, verbose_name='Author', on_delete=models.DO_NOTHING)
    created_time = models.DateTimeField(auto_now_add=True, editable=False, verbose_name='Create Time')

    class Meta:
        verbose_name = verbose_name_plural = 'Tag Table'

    def __str__(self):
        return self.name


class Post(models.Model):
    STATUS_NORMAL = 1
    STATUS_DELETE = 0
    STATUS_DRAFT = 2
    STATUS_ITEMS = (
        (STATUS_NORMAL, 'Normal'),
        (STATUS_DELETE, 'Delete'),
        (STATUS_DRAFT, 'Draft')
    )
    title = models.CharField(max_length=255, verbose_name='Title')
    desc = models.CharField(max_length=1024, blank=True, verbose_name='Desc')
    content = models.TextField(verbose_name='Content', help_text='Must be MarkDown')
    content_html = models.TextField(verbose_name='Html Content', blank=True, editable=False)
    status = models.PositiveIntegerField(default=STATUS_NORMAL, choices=STATUS_ITEMS, verbose_name='Status')
    category = models.ForeignKey(Category, verbose_name='Category', on_delete=models.DO_NOTHING)
    tag = models.ManyToManyField(Tag, verbose_name='Tag')
    owner = models.ForeignKey(User, verbose_name='Author', on_delete=models.DO_NOTHING)
    created_time = models.DateTimeField(auto_now_add=True, editable=False, verbose_name='Create Time')
    pv = models.PositiveIntegerField(default=1)
    uv = models.PositiveIntegerField(default=1)

    class Meta:
        verbose_name = verbose_name_plural = 'Post Table'
        ordering = ['-id']   # 根据ID降序

    def __str__(self):
        return self.title

    @cached_property
    def tags(self):
        return ','.join(self.tag.values_list('name', flat=True))

    @staticmethod
    def get_by_tag(tag_id):
        try:
            tag = Tag.objects.get(id=tag_id)
        except Tag.DoesNotExist:
            tag = None
            plist = []
        else:
            plist = tag.post_set.filter(status=Post.STATUS_NORMAL).select_related('owner', 'category')

        return plist, tag

    @staticmethod
    def get_by_category(category_id):
        try:
            category = Category.objects.get(id=category_id)
        except Category.DoesNotExist:
            category = None
            post_list = []
        else:
            post_list = category.post_set.filter(status=Post.STATUS_NORMAL).select_related('owner', 'category')
        return post_list, category

    @classmethod
    def latest_posts(cls):
        return cls.objects.filter(status=cls.STATUS_NORMAL).order_by('-pk')

    @classmethod
    def hot_posts(cls):
        return cls.objects.filter(status=cls.STATUS_NORMAL).order_by('-pv')

    def save(self, *args, **kwargs):
        self.content_html = mistune.markdown(self.content)
        super().save(*args, **kwargs)
